package com.gitee.limaozhi.socket.lesson03.example4;

import java.util.ArrayList;
import java.util.List;

/**
 * @author hzlimaozhi
 * @date 2019/08/08 10:09
 */
public class HttpRequestBuilder {

    private LineBuffer lineBuffer = new LineBuffer();

    private HttpRequest request = null;
    private int contentLength = 0;
    private boolean blankLine = false;

    public HttpRequest addBytes(byte[] bytes) {
        lineBuffer.add(bytes);

        // 未到空行，读取行
        if (!blankLine) {
            List<String> lines = lineBuffer.getLines();
            for (String line : lines) {
                if (request == null) {
                    // 第一行
                    request = new HttpRequest();
                    String[] parts = line.split(" ");
                    request.setMethod(parts[0]);
                    request.setUri(parts[1]);
                    request.setVersion(parts[2]);

                } else if (!blankLine) {
                    if (line != "") {
                        // 头部行
                        String[] parts = line.split(": ");
                        request.addHeader(parts[0], parts[1]);
                        if (parts[0].equalsIgnoreCase("Content-Length")) {
                            contentLength = Integer.parseInt(parts[1]);
                        }

                    } else {
                        // 空行
                        blankLine = true;
                        if (contentLength == 0) {
                            // 无主体
                            HttpRequest result = request;
                            request = null;
                            contentLength = 0;
                            blankLine = false;
                            return result;
                        }
                    }

                } else {
                    // 主体
                    throw new IllegalStateException();
                }
            }
        }

        // 已过空行，读取主体
        if (blankLine) {
            String content = lineBuffer.getContent(contentLength);
            if (content != null) {
                request.setContent(content);
                HttpRequest result = request;
                request = null;
                contentLength = 0;
                blankLine = false;
                return result;
            }
        }

        return null;
    }

    static class LineBuffer {

        private byte[] buffer = new byte[1024];

        private int count;

        private int left() {
            return buffer.length - count;
        }

        private void grow(int length) {
            int diff = length - left();
            if (diff > 0) {
                // 不够
                int newLength = buffer.length + diff * 2;
                byte[] newBuffer = new byte[newLength];
                System.arraycopy(buffer, 0, newBuffer, 0, count);
                buffer = newBuffer;
            }
        }

        public LineBuffer add(byte[] bytes) {
            grow(bytes.length);
            System.arraycopy(bytes, 0, buffer, count, bytes.length);
            count += bytes.length;
            return this;
        }

        public List<String> getLines() {
            List<String> lines = new ArrayList<>();
            int lineStart = 0;
            for (int index = 0; index < count; index++) {
                if (buffer[index] == '\r') {
                    if (index == count - 1) {
                        // 已结束
                        break;

                    } else if (buffer[index + 1] != '\n') {
                        throw new IllegalArgumentException("CR后无LF");

                    } else {
                        // 取行
                        if (lineStart == index) {
                            // 空行
                            lines.add("");

                            // 下一行
                            lineStart = index + 2;

                            // 遇到空行停止，下面是主体或下一个请求
                            break;
                        } else {
                            lines.add(new String(buffer, lineStart, index - lineStart));

                            // 下一行
                            lineStart = index + 2;
                        }
                        // 跳到\n
                        index++;
                    }
                }
            }

            if (lineStart == count) {
                count = 0;
            } else if (lineStart > 0) {
                count -= lineStart;
                System.arraycopy(buffer, lineStart, buffer, 0, count);
            }
            return lines;
        }

        public String getContent(int size) {
            if (count >= size) {
                String content = new String(buffer, 0, size);
                if (count == size) {
                    count = 0;
                } else {
                    count -= size;
                    System.arraycopy(buffer, size, buffer, 0, count);
                }
                return content;
            }
            return null;
        }

    }

}
